awtk

您所在的位置:网站首页 js fifo awtk

awtk

#awtk| 来源: 网络整理| 查看: 265

目录 一、前言二、适配 JS 版本的序列点数据(FIFO)2.1 series_fifo_js 的接口2.1 series_fifo_js 的实现 三、自定义 binder四、JS 语言绑定 chart view 控件4.1 注册自定义 binder4.2 创建并绑定 Model4.3 Model 变化4.3.1 使用自定义接口4.3.2 使用原生接口

一、前言

awtk-widget-chart-view 是 AWTK 提供的图表自定义控件,该控件包含:曲线图、柱状图和饼图。前段时 间记录了该控件适配 AWTK-MVVM C版本的过程,具体请参考:awtk-widget-chart-view-mvvm C版本适配笔记,这次记录一下适配 JS 版本的过程。

AWTK是 ZLG 开发的开源 GUI 引擎,官网地址:https://www.zlg.cn/index/pub/awtk.html。 AWTK GitHub 仓库:http://github.com/zlgopen/awtk-mvvm

AWTK-MVVM是一套用C语言开发的,专门为嵌入式平台优化的MVVM框架。它实现了数据绑定、命令绑定和窗口导航等基本功能。 AWTK-MVVM GitHub 仓库:http://github.com/zlgopen/awtk-mvvm

二、适配 JS 版本的序列点数据(FIFO)

chart view 图表控件的绝大部分属性都可使用 awtk-mvvm 缺省的方法进行绑定,但 series 控件 fifo 属性比较特殊,它是一个自定义的先进先出队列,用于储存图表的序列点数据。因此,数据绑定时,需要指定一个特殊的 Model。C 语言中可以调用 serties_fifo_default_create() 接口创建该 Model;JS语言中则需使用 JS 的 Array,本项目所实现的自定义 binder 会将 Array 适配为 series 所需的 fifo。

简单理解,即基于 JS 的原生 Array 数据类型实现一个 C 版本的先进先出队列 FIFO,也就是 series_fifo_js ,此处基于 JerryScript 实现 JS 与 C 之间的适配。

JerryScript 是一个轻量级的 JavaScript 引擎,它可以运行在受限制的设备上,官网地址:https://jerryscript.net/。

2.1 series_fifo_js 的接口

series_fifo_js 的接口如下:

#ifndef TK_SERIES_FIFO_JS_H #define TK_SERIES_FIFO_JS_H #include "base/series_fifo.h" #include "mvvm/jerryscript/object_js_default.h" BEGIN_C_DECLS struct _series_fifo_js_t; typedef struct _series_fifo_js_t series_fifo_js_t; typedef ret_t (*series_fifo_jsobj_set_t)(object_t* obj, jsvalue_t jsindex, jsvalue_t array); /** * @class series_fifo_js_t * @parent series_fifo_t * * 将jerry script Array适配成series_fifo。 * */ struct _series_fifo_js_t { series_fifo_t base; /** * @property {uint32_t} capacity * @annotation ["readable"] * FIFO的容量大小。 */ uint32_t capacity; /** * @property {uint32_t} unit_size * @annotation ["readable"] * FIFO中单个元素的大小。 */ uint32_t unit_size; /** * @property {uint32_t} capacity * @annotation ["readable"] * FIFO的容量大小。 */ series_fifo_jsobj_set_t jsobj_set; /*private*/ object_t* native_obj; uint8_t* temp; uint8_t* event_data; }; /** * @method series_fifo_js_create * 创建series_fifo_js对象。 * * @annotation ["constructor"] * @param {object_t} native_obj jerry script Array的obj对象。 * @param {uint32_t} capacity FIFO的初始容量。 * @param {const char*} type FIFO数据类型。 * * @return {object_t*} 返回object对象。 */ object_t* series_fifo_js_create(object_t* native_obj, uint32_t capacity, const char* type); /* helper function */ ret_t series_fifo_jsobj_set(object_t* obj, jsvalue_t jsindex, jsvalue_t array); ret_t series_fifo_jsobj_push(object_t* obj, jsvalue_t array); #define SERIES_FIFO_JS(obj) (series_fifo_js_t*)(obj) END_C_DECLS #endif /*TK_SERIES_FIFO_JS_H*/ 2.1 series_fifo_js 的实现

series_fifo_js 的实现如下:

#include "tkc/mem.h" #include "tkc/utils.h" #include "tkc/value.h" #include "series_fifo_js.h" #include "base/series_fifo_default.h" #define FIFO_DATA_VALUE "value" #define FIFO_DATA_COLOR "color" #define FIFO_DATA_MIN "min" #define FIFO_DATA_MAX "max" static int series_fifo_js_base_compare(object_t* obj, const void* a, const void* b) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL, RET_BAD_PARAMS); return memcmp(a, b, fifo->unit_size); } static void* series_fifo_js_default_get(object_t* obj, uint32_t index) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t elem = jsobj_get_prop_value_by_index(jsobj, index); if (jsvalue_check(elem) == RET_OK) { float_t data = 0; jsvalue_t value = jsobj_get_prop_value(elem, FIFO_DATA_VALUE); data = jsvalue_to_number(value); memcpy(fifo->temp, &data, sizeof(float_t)); jsvalue_unref(value); jsvalue_unref(elem); } return fifo->temp; } static void* series_fifo_js_colorful_get(object_t* obj, uint32_t index) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t elem = jsobj_get_prop_value_by_index(jsobj, index); if (jsvalue_check(elem) == RET_OK) { series_data_colorful_t data = {0}; jsvalue_t value = jsobj_get_prop_value(elem, FIFO_DATA_VALUE); jsvalue_t color = jsobj_get_prop_value(elem, FIFO_DATA_COLOR); data.v = jsvalue_to_number(value); data.c.color = jsvalue_to_number(color); memcpy(fifo->temp, &data, sizeof(series_data_colorful_t)); jsvalue_unref(value); jsvalue_unref(color); jsvalue_unref(elem); } return fifo->temp; } static void* series_fifo_js_minmax_get(object_t* obj, uint32_t index) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t elem = jsobj_get_prop_value_by_index(jsobj, index); if (jsvalue_check(elem) == RET_OK) { series_data_minmax_t data = {0}; jsvalue_t min_v = jsobj_get_prop_value(elem, FIFO_DATA_MIN); jsvalue_t max_v = jsobj_get_prop_value(elem, FIFO_DATA_MAX); data.min = jsvalue_to_number(min_v); data.max = jsvalue_to_number(max_v); memcpy(fifo->temp, &data, sizeof(series_data_minmax_t)); jsvalue_unref(min_v); jsvalue_unref(max_v); jsvalue_unref(elem); } return fifo->temp; } static uint8_t* series_fifo_js_prepare_set(object_t* obj, uint32_t* index, const void* data, uint32_t* nr) { int32_t i = 0; int32_t over_nr = 0; series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t unit_size = fifo->unit_size; uint8_t* start = (uint8_t*)(data); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t shift = jsobj_get_prop_value(jsobj, "shift"); jsvalue_t args[1]; if (*nr > fifo->capacity) { if (start != NULL) { start += (*nr - fifo->capacity) * unit_size; } *nr = fifo->capacity; } over_nr = *index + *nr - fifo->capacity; if (over_nr > 0) { args[0] = JS_UNDEFINED; for (i = 0; i value_t v; int32_t i = 0; series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t unit_size = fifo->unit_size; jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t splice = jsobj_get_prop_value(jsobj, "splice"); uint8_t* start = series_fifo_js_prepare_set(obj, &index, data, &nr); jsvalue_t args[3]; for (i = 0; i memcpy(&elem, start + unit_size * i, unit_size); } args[0] = jsvalue_from_number(index + i); args[1] = jsvalue_from_number(1); args[2] = JS_EMPTY_OBJ; value_set_float(&v, elem); jsobj_set_prop(args[2], FIFO_DATA_VALUE, &v, NULL); jsvalue_unref(jsfunc_call(splice, jsobj, args, 3)); jsvalue_unref(args[0]); jsvalue_unref(args[1]); jsvalue_unref(args[2]); } jsvalue_unref(splice); return RET_OK; } static ret_t series_fifo_js_colorful_set(object_t* obj, uint32_t index, const void* data, uint32_t nr) { value_t v; int32_t i = 0; series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t unit_size = fifo->unit_size; jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t splice = jsobj_get_prop_value(jsobj, "splice"); uint8_t* start = series_fifo_js_prepare_set(obj, &index, data, &nr); jsvalue_t args[3]; for (i = 0; i 0}; if (start != NULL) { memcpy(&elem, start + unit_size * i, unit_size); } args[0] = jsvalue_from_number(index + i); args[1] = jsvalue_from_number(1); args[2] = JS_EMPTY_OBJ; value_set_float(&v, elem.v); jsobj_set_prop(args[2], FIFO_DATA_VALUE, &v, NULL); value_set_uint32(&v, elem.c.color); jsobj_set_prop(args[2], FIFO_DATA_COLOR, &v, NULL); jsvalue_unref(jsfunc_call(splice, jsobj, args, 3)); jsvalue_unref(args[0]); jsvalue_unref(args[1]); jsvalue_unref(args[2]); } jsvalue_unref(splice); return RET_OK; } static ret_t series_fifo_js_minmax_set(object_t* obj, uint32_t index, const void* data, uint32_t nr) { value_t v; int32_t i = 0; series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t unit_size = fifo->unit_size; jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); jsvalue_t splice = jsobj_get_prop_value(jsobj, "splice"); uint8_t* start = series_fifo_js_prepare_set(obj, &index, data, &nr); jsvalue_t args[3]; for (i = 0; i 0}; if (start != NULL) { memcpy(&elem, start + unit_size * i, unit_size); } args[0] = jsvalue_from_number(index + i); args[1] = jsvalue_from_number(1); args[2] = JS_EMPTY_OBJ; value_set_float(&v, elem.min); jsobj_set_prop(args[2], FIFO_DATA_MIN, &v, NULL); value_set_float(&v, elem.max); jsobj_set_prop(args[2], FIFO_DATA_MAX, &v, NULL); jsvalue_unref(jsfunc_call(splice, jsobj, args, 3)); jsvalue_unref(args[0]); jsvalue_unref(args[1]); jsvalue_unref(args[2]); } jsvalue_unref(splice); return RET_OK; } static object_t* series_fifo_js_base_part_clone(object_t* obj, uint32_t index, uint32_t nr) { return_value_if_fail(obj != NULL, NULL); object_t* clone = NULL; series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL, NULL); clone = series_fifo_default_create(nr, fifo->unit_size); series_fifo_default_t* fifo_clone = SERIES_FIFO_DEFAULT(clone); uint32_t unit_size = fifo->unit_size; if (fifo_clone) { uint8_t* data = fifo_clone->buffer; for (int32_t i = 0; i series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL && capacity > 0, RET_BAD_PARAMS); fifo->capacity = capacity; return RET_OK; } static uint32_t series_fifo_jsobj_get_length(jsvalue_t jsobj) { jsvalue_t value = jsobj_get_prop_value(jsobj, "length"); uint32_t length = jsvalue_to_number(value); jsvalue_unref(value); return length; } static ret_t series_fifo_jsobj_prepare_set(object_t* obj, jsvalue_t array, uint32_t* index, uint32_t* nr) { uint32_t i = 0; jsvalue_t args[2]; jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); uint32_t capacity = object_get_prop_uint32(obj, SERIES_FIFO_PROP_CAPACITY, 0); uint32_t size = object_get_prop_uint32(obj, SERIES_FIFO_PROP_SIZE, 0); jsvalue_t push = jsobj_get_prop_value(jsobj, "push"); jsvalue_t shift = jsobj_get_prop_value(jsobj, "shift"); return_value_if_fail(jsvalue_check(jsobj) == RET_OK, RET_BAD_PARAMS); args[0] = JS_UNDEFINED; args[1] = JS_EMPTY_OBJ; if (*index + *nr > size) { for (i = 0; i jsvalue_unref(jsfunc_call(shift, array, args, 1)); } jsvalue_unref(jsfunc_call(push, jsobj, &args[1], 1)); } if (*nr > capacity) { *index = 0; for (i = 0; i uint32_t i = 0; uint32_t unit_size = sizeof(float_t); series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t index = jsvalue_to_number(jsindex); uint32_t nr = series_fifo_jsobj_get_length(array); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); return_value_if_fail(jsvalue_check(jsobj) == RET_OK, RET_BAD_PARAMS); series_fifo_jsobj_prepare_set(obj, array, &index, &nr); if (fifo->event_data != NULL) { TKMEM_FREE(fifo->event_data); } series_fifo_set_event_t e; fifo->event_data = TKMEM_ZALLOCN(uint8_t, nr * unit_size); series_fifo_set_event_init(&e, EVT_SERIES_FIFO_WILL_SET, obj); e.index = index; e.nr = nr; for (i = 0; i uint32_t i = 0; uint32_t unit_size = sizeof(series_data_colorful_t); series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t index = jsvalue_to_number(jsindex); uint32_t nr = series_fifo_jsobj_get_length(array); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); return_value_if_fail(jsvalue_check(jsobj) == RET_OK, RET_BAD_PARAMS); series_fifo_jsobj_prepare_set(obj, array, &index, &nr); if (fifo->event_data != NULL) { TKMEM_FREE(fifo->event_data); } series_fifo_set_event_t e; fifo->event_data = TKMEM_ZALLOCN(uint8_t, nr * unit_size); series_fifo_set_event_init(&e, EVT_SERIES_FIFO_WILL_SET, obj); e.index = index; e.nr = nr; for (i = 0; i 0}; jsvalue_t elem = jsobj_get_prop_value_by_index(array, i); jsvalue_t value = jsobj_get_prop_value(elem, FIFO_DATA_VALUE); jsvalue_t color = jsobj_get_prop_value(elem, FIFO_DATA_COLOR); data.v = jsvalue_to_number(value); data.c.color = jsvalue_to_number(color); memcpy(fifo->event_data + unit_size * i, &data, unit_size); jsvalue_unref(value); jsvalue_unref(color); jsvalue_unref(elem); } e.data = (void*)fifo->event_data; emitter_dispatch(EMITTER(obj), (event_t*)&e); return RET_OK; } static ret_t series_fifo_jsobj_minmax_set(object_t* obj, jsvalue_t jsindex, jsvalue_t array) { uint32_t i = 0; uint32_t unit_size = sizeof(series_data_minmax_t); series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); uint32_t index = jsvalue_to_number(jsindex); uint32_t nr = series_fifo_jsobj_get_length(array); jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); return_value_if_fail(jsvalue_check(jsobj) == RET_OK, RET_BAD_PARAMS); series_fifo_jsobj_prepare_set(obj, array, &index, &nr); if (fifo->event_data != NULL) { TKMEM_FREE(fifo->event_data); } series_fifo_set_event_t e; fifo->event_data = TKMEM_ZALLOCN(uint8_t, nr * unit_size); series_fifo_set_event_init(&e, EVT_SERIES_FIFO_WILL_SET, obj); e.index = index; e.nr = nr; for (i = 0; i 0}; jsvalue_t elem = jsobj_get_prop_value_by_index(array, i); jsvalue_t min_v = jsobj_get_prop_value(elem, FIFO_DATA_MIN); jsvalue_t max_v = jsobj_get_prop_value(elem, FIFO_DATA_MAX); data.min = jsvalue_to_number(min_v); data.max = jsvalue_to_number(max_v); memcpy(fifo->event_data + unit_size * i, &data, unit_size); jsvalue_unref(min_v); jsvalue_unref(max_v); jsvalue_unref(elem); } e.data = (void*)fifo->event_data; emitter_dispatch(EMITTER(obj), (event_t*)&e); return RET_OK; } ret_t series_fifo_jsobj_set(object_t* obj, jsvalue_t jsindex, jsvalue_t array) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL, RET_BAD_PARAMS); return fifo->jsobj_set(obj, jsindex, array); } ret_t series_fifo_jsobj_push(object_t* obj, jsvalue_t array) { jsvalue_t args[1]; jsvalue_t jsobj = object_get_prop_uint32(obj, JSOBJ_PROP_NATIVE_OBJ, 0); return_value_if_fail(jsvalue_check(jsobj) == RET_OK, RET_BAD_PARAMS); jsvalue_t push = jsobj_get_prop_value(jsobj, "push"); jsvalue_t shift = jsobj_get_prop_value(jsobj, "shift"); uint32_t capacity = object_get_prop_uint32(obj, SERIES_FIFO_PROP_CAPACITY, 0); args[0] = JS_UNDEFINED; for (uint32_t i = 0; i jsvalue_unref(jsfunc_call(shift, jsobj, args, 1)); } jsvalue_t elem = jsobj_get_prop_value_by_index(array, i); jsvalue_unref(jsfunc_call(push, jsobj, &elem, 1)); jsvalue_unref(elem); } jsvalue_unref(args[0]); jsvalue_unref(push); jsvalue_unref(shift); series_fifo_push_event_t e; series_fifo_push_event_init(&e, EVT_SERIES_FIFO_PUSH, obj); e.nr = series_fifo_jsobj_get_length(array); emitter_dispatch(EMITTER(obj), (event_t*)&e); return RET_OK; } static ret_t series_fifo_js_on_destroy(object_t* obj) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL, RET_BAD_PARAMS); OBJECT_UNREF(fifo->native_obj); if (fifo->temp) { TKMEM_FREE(fifo->temp); } if (fifo->event_data) { TKMEM_FREE(fifo->event_data); } return RET_OK; } static ret_t series_fifo_js_get_prop(object_t* obj, const char* name, value_t* v) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL, RET_BAD_PARAMS); jsvalue_t jsobj = (OBJECT_JS_BASE(fifo->native_obj))->jsobj; if (tk_str_eq(name, JSOBJ_PROP_NATIVE_OBJ)) { value_set_uint32(v, jsobj); return RET_OK; } else if (tk_str_eq(name, SERIES_FIFO_PROP_CAPACITY)) { value_set_uint32(v, fifo->capacity); return RET_OK; } else if (tk_str_eq(name, SERIES_FIFO_PROP_SIZE)) { value_set_uint32(v, series_fifo_jsobj_get_length(jsobj)); return RET_OK; } else if (tk_str_eq(name, SERIES_FIFO_PROP_CURSOR)) { value_set_uint32(v, series_fifo_jsobj_get_length(jsobj) - 1); return RET_OK; } else if (tk_str_eq(name, SERIES_FIFO_PROP_UNIT_SIZE)) { value_set_uint32(v, fifo->unit_size); return RET_OK; } return RET_NOT_FOUND; } static ret_t series_fifo_js_set_prop(object_t* obj, const char* name, const value_t* v) { series_fifo_js_t* fifo = SERIES_FIFO_JS(obj); return_value_if_fail(fifo != NULL, RET_BAD_PARAMS); if (tk_str_eq(name, SERIES_FIFO_PROP_CAPACITY)) { series_fifo_js_base_set_capacity(obj, value_uint32(v)); return RET_OK; } else if (tk_str_eq(name, SERIES_FIFO_PROP_SIZE)) { return RET_OK; } else if (tk_str_eq(name, SERIES_FIFO_PROP_CURSOR)) { return RET_OK; } return RET_NOT_FOUND; } static const object_vtable_t s_object_vtable = {.type = "series_fifo_js", .desc = "series_fifo_js", .size = sizeof(series_fifo_js_t), .is_collection = FALSE, .on_destroy = series_fifo_js_on_destroy, .get_prop = series_fifo_js_get_prop, .set_prop = series_fifo_js_set_prop}; static const series_fifo_vtable_t s_series_fifo_js_default_vtable = { .part_clone = series_fifo_js_base_part_clone, .get = series_fifo_js_default_get, .set = series_fifo_js_default_set, .compare = series_fifo_js_base_compare, .set_capacity = series_fifo_js_base_set_capacity, }; static const series_fifo_vtable_t s_series_fifo_js_colorful_vtable = { .part_clone = series_fifo_js_base_part_clone, .get = series_fifo_js_colorful_get, .set = series_fifo_js_colorful_set, .compare = series_fifo_js_base_compare, .set_capacity = series_fifo_js_base_set_capacity, }; static const series_fifo_vtable_t s_series_fifo_js_minmax_vtable = { .part_clone = series_fifo_js_base_part_clone, .get = series_fifo_js_minmax_get, .set = series_fifo_js_minmax_set, .compare = series_fifo_js_base_compare, .set_capacity = series_fifo_js_base_set_capacity, }; static object_t* series_fifo_js_create_internal(object_t* native_obj, uint32_t capacity, uint32_t unit_size, const series_fifo_vtable_t* vt, series_fifo_jsobj_set_t jsobj_set) { object_t* obj = NULL; series_fifo_t* series_fifo = NULL; series_fifo_js_t* fifo = NULL; obj = object_create(&s_object_vtable); series_fifo = SERIES_FIFO(obj); fifo = SERIES_FIFO_JS(obj); return_value_if_fail(obj != NULL && series_fifo != NULL && fifo != NULL, NULL); series_fifo->vt = vt; OBJECT_REF(native_obj); fifo->capacity = capacity; fifo->unit_size = unit_size; fifo->jsobj_set = jsobj_set; fifo->native_obj = native_obj; fifo->temp = TKMEM_ZALLOCN(uint8_t, unit_size * 1); fifo->event_data = NULL; return obj; } object_t* series_fifo_js_create(object_t* native_obj, uint32_t capacity, const char* type) { uint32_t unit_size = sizeof(float_t); series_fifo_jsobj_set_t jsobj_set = series_fifo_jsobj_default_set; const series_fifo_vtable_t* vt = &s_series_fifo_js_default_vtable; return_value_if_fail(native_obj != NULL && capacity > 0 && type != NULL, NULL); if (strstr(type, "colorful")) { vt = &s_series_fifo_js_colorful_vtable; jsobj_set = series_fifo_jsobj_colorful_set; unit_size = sizeof(series_data_colorful_t); } else if (strstr(type, "minmax")) { vt = &s_series_fifo_js_minmax_vtable; jsobj_set = series_fifo_jsobj_minmax_set; unit_size = sizeof(series_data_minmax_t); } return series_fifo_js_create_internal(native_obj, capacity, unit_size, vt, jsobj_set); } 三、自定义 binder

awtk-widget-chart-view-mvvm 的自定义 binder 需要将 JS ViewModel 中指定的数组数据与 series 控件的 fifo 属性绑定起来,并且当数组对象被修改时,需要重新绑定,代码如下:

#include "awtk.h" #include "mvvm/mvvm.h" #include "chart_view/series.h" #include "chart_view_custom_binder.h" #include "jerryscript/series_fifo_js.h" #include "mvvm/jerryscript/jsobj_4_mvvm.h" #ifdef WITH_JERRYSCRIPT #define VIEW_MODEL_FUNC_FIFO_SET "requestFifoSet" #define VIEW_MODEL_FUNC_FIFO_PUSH "requestFifoPush" static JSFUNC_DECL(chart_view_series_fifo_set) { view_model_t* vm = VIEW_MODEL(js_view_model_get_native_ptr(call_info_p->this_value)); return_value_if_fail(vm != NULL && args_count >= 3, JS_UNDEFINED); int32_t i = 0; series_fifo_set_event_t e; series_fifo_set_event_init(&e, EVT_SERIES_FIFO_SET, (void*)vm); e.ctx = (void*)args_p; emitter_dispatch(EMITTER(vm), (event_t*)&e); return jsvalue_from_number(RET_OK); } static JSFUNC_DECL(chart_view_series_fifo_push) { view_model_t* vm = VIEW_MODEL(js_view_model_get_native_ptr(call_info_p->this_value)); return_value_if_fail(vm != NULL && args_count >= 2, JS_UNDEFINED); series_fifo_push_event_t e; series_fifo_push_event_init(&e, EVT_SERIES_FIFO_PUSH, (void*)vm); e.ctx = (void*)args_p; emitter_dispatch(EMITTER(vm), (event_t*)&e); return jsvalue_from_number(RET_OK); } static bool_t chart_view_series_is_skip_event(data_binding_t* rule, jsvalue_t jsname) { str_t temp; bool_t ret = false; char* target = NULL; str_init(&temp, 0); target = jsvalue_to_utf8(jsname, &temp); if (!tk_str_eq(target, rule->path)) { ret = TRUE; } str_reset(&temp); return ret; } static ret_t chart_view_series_fifo_on_set(void* ctx, event_t* e) { data_binding_t* rule = DATA_BINDING(ctx); series_fifo_set_event_t* evt = (series_fifo_set_event_t*)e; jsvalue_t* args = (jsvalue_t*)evt->ctx; return_value_if_fail(rule != NULL && args != NULL, RET_BAD_PARAMS); if (!chart_view_series_is_skip_event(rule, args[0])) { value_t v; view_model_t* vm = VIEW_MODEL(e->target); return_value_if_fail(vm != NULL, RET_BAD_PARAMS); if (view_model_get_prop(vm, rule->path, &v) == RET_OK && v.type == VALUE_TYPE_OBJECT) { object_t* fifo = NULL; object_t* native_obj = value_object(&v); widget_t* widget = BINDING_RULE_WIDGET(rule); series_t* series = SERIES(widget); return_value_if_fail(series != NULL, RET_BAD_PARAMS); fifo = series->fifo; if ((SERIES_FIFO_JS(fifo))->native_obj != native_obj) { series_set_fifo(widget, native_obj); fifo = series->fifo; } series_fifo_jsobj_set(fifo, args[1], args[2]); } } return RET_OK; } static ret_t chart_view_series_fifo_on_push(void* ctx, event_t* e) { data_binding_t* rule = DATA_BINDING(ctx); series_fifo_push_event_t* evt = (series_fifo_push_event_t*)e; jsvalue_t* args = (jsvalue_t*)evt->ctx; return_value_if_fail(rule != NULL && args != NULL, RET_BAD_PARAMS); if (!chart_view_series_is_skip_event(rule, args[0])) { value_t v; view_model_t* vm = VIEW_MODEL(e->target); return_value_if_fail(vm != NULL, RET_BAD_PARAMS); if (view_model_get_prop(vm, rule->path, &v) == RET_OK && v.type == VALUE_TYPE_OBJECT) { object_t* fifo = NULL; object_t* native_obj = value_object(&v); widget_t* widget = BINDING_RULE_WIDGET(rule); series_t* series = SERIES(widget); return_value_if_fail(series != NULL, RET_BAD_PARAMS); fifo = series->fifo; if ((SERIES_FIFO_JS(fifo))->native_obj != native_obj) { series_set_fifo(widget, native_obj); fifo = series->fifo; } series_fifo_jsobj_push(fifo, args[1]); } } return RET_OK; } static ret_t chart_view_series_set_view_model_func(view_model_t* vm) { jsvalue_t jsvm = object_get_prop_uint32(OBJECT(vm), JSOBJ_PROP_NATIVE_OBJ, 0); return_value_if_fail(jsvalue_check(jsvm) == RET_OK, RET_BAD_PARAMS); if (!jsobj_has_prop_func(jsvm, VIEW_MODEL_FUNC_FIFO_SET)) { jsobj_set_prop_func(jsvm, VIEW_MODEL_FUNC_FIFO_SET, chart_view_series_fifo_set); } if (!jsobj_has_prop_func(jsvm, VIEW_MODEL_FUNC_FIFO_PUSH)) { jsobj_set_prop_func(jsvm, VIEW_MODEL_FUNC_FIFO_PUSH, chart_view_series_fifo_push); } return RET_OK; } static object_t* chart_view_series_prepare_fifo_mvvm(widget_t* widget, void* ctx, object_t* obj) { value_t v; object_t* curr = NULL; object_t* fifo = NULL; uint32_t capacity = 0; const char* curr_type = NULL; binding_rule_t* rule = BINDING_RULE(ctx); return_value_if_fail(rule != NULL, NULL); if (widget_get_prop(widget, SERIES_PROP_FIFO, &v) == RET_OK) { curr = value_object(&v); curr_type = object_get_type(curr); if (tk_str_eq(curr_type, "series_fifo_js") && (SERIES_FIFO_JS(curr))->native_obj == obj) { return curr; } } capacity = widget_get_prop_int(widget, SERIES_PROP_CAPACITY, 0); fifo = series_fifo_js_create(obj, capacity, widget_get_type(widget)); return fifo; } static ret_t chart_view_series_bind(binding_context_t* ctx, binding_rule_t* rule) { if (binding_rule_is_data_binding(rule)) { widget_t* widget = BINDING_RULE_WIDGET(rule); data_binding_t* data_rule = DATA_BINDING(rule); return_value_if_fail(widget != NULL && data_rule != NULL && ctx != NULL, RET_BAD_PARAMS); if (tk_str_eq(data_rule->prop, SERIES_PROP_FIFO) && widget_is_series(widget)) { view_model_t* vm = ctx->view_model; return_value_if_fail(vm != NULL, RET_BAD_PARAMS); if (strstr(object_get_type(OBJECT(vm)), "jerryscript")) { series_set_prepare_fifo(widget, chart_view_series_prepare_fifo_mvvm, (void*)rule); chart_view_series_set_view_model_func(vm); emitter_on(EMITTER(vm), EVT_SERIES_FIFO_SET, chart_view_series_fifo_on_set, rule); emitter_on(EMITTER(vm), EVT_SERIES_FIFO_PUSH, chart_view_series_fifo_on_push, rule); } } } return RET_OK; } #else static ret_t chart_view_series_bind(binding_context_t* ctx, binding_rule_t* rule) { return RET_OK; } #endif /*WITH_JERRYSCRIPT*/ ret_t chart_view_custom_binder_register(void) { custom_binder_register(WIDGET_TYPE_LINE_SERIES, chart_view_series_bind); custom_binder_register(WIDGET_TYPE_LINE_SERIES_COLORFUL, chart_view_series_bind); custom_binder_register(WIDGET_TYPE_BAR_SERIES, chart_view_series_bind); custom_binder_register(WIDGET_TYPE_BAR_SERIES_MINMAX, chart_view_series_bind); return RET_OK; } 四、JS 语言绑定 chart view 控件 4.1 注册自定义 binder JS 语言绑定 chart view 控件需要注册自定义 binder,比如,在初始化时注册自定义 binder: // demos\jsdemo\application.c #include "awtk.h" #include "mvvm/mvvm.h" #include "chart_view_register.h" #include "chart_view_custom_binder.h" ret_t application_init() { chart_view_register(); chart_view_custom_binder_register(); navigator_to("system_bar"); navigator_to("home_page"); return RET_OK; } 4.2 创建并绑定 Model

在 JS 中,使用 Array 代替 FIFO 数据类型,比如创建数组 fifo1 作为 Model:

// design\default\scripts\line_normal.js ViewModel('line_normal', { data: { fifo1: [], ... } ... });

在 XML 的界面描述文件中,通过 v-data 属性来指定 Model 即可:

... ... 4.3 Model 变化

当 Model 的数据需要变化并通知 View 进行更新时,有以下几种方式:

4.3.1 使用自定义接口

MVVM 绑定过程中,自定义 binder 会在 ViewModel 上新增以下接口:

注意:以下新增接口只能在 ViewModel 中调用,且这些接口默认会触发 series 的序列点变化动画。

requestFifoSet 接口

声明如下:

/** * @method requestFifoSet * 从特定位置开始设置数据。 * * @param {string} name Model名称。 * @param {number} index 位置索引。 * @param {array} data 数据数组。 */ requestFifoSet(name: string, index: number, data: []);

示例用法:

// design\default\scripts\line_normal.js ViewModel('line_normal', { methods: { newGraph: function () { var rand_data1 = this._randDataGen(this.capacity); var rand_data2 = this._randDataGen(this.capacity); this.requestFifoSet('fifo1', 0, rand_data1); this.requestFifoSet('fifo2', 0, rand_data2); }, } }); requestFifoPush 接口

声明如下:

/** * @method requestFifoPush * 在尾部追加数据。 * * @param {string} name Model名称。 * @param {array} data 数据数组。 */ requestFifoPush(name: string, data: []);

示例用法:

// design\default\scripts\line_normal.js ViewModel('line_normal', { methods: { onTimer: function () { var rand_data1 = this._randDataGen(5); var rand_data2 = this._randDataGen(5); this.requestFifoPush('fifo1', rand_data1); this.requestFifoPush('fifo2', rand_data2); return RET_REPEAT; } } }); 4.3.2 使用原生接口

由于 Model 本身是一个数组,因此也可以直接用 JS Array 的原生接口修改 Model 数据,比如,push、shift等接口,但修改后数据并不会马上更新到界面,需要调用 ViewModel 提供的 notifyPropsChanged() 接口通知界面更新。

注意:如果使用 Array 原生接口修改 Model 数据时改变了 Model 对象,界面更新时将自动重新绑定新的 Model 对象。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3